//////////////////////////////////////////////////////////////////////
////                                                              ////
////  MemoryPeripherals.v                                         ////
////                                                              ////
////                                                              ////
////  This file is part of the "Pico E12" project                 ////
////  http://www.picocomputing.com                                ////
////                                                              ////
//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2005, Picocomputing, Inc.                      ////
//// http://www.picocomputing.com/                                ////
////                                                              ////
//////////////////////////////////////////////////////////////////////

//This is where memory peripherals attach
`timescale 10ns / 1ns
`include "PicoDefines.v"

module MemoryPeripherals(
   input CLOCK1,                                                          //System Generator Clock Input (50 MHz Free Running)
   input CLOCK2,                                                          //50 MHz
   input CLOCKY9,
   input  CFClock,                                                        //200 MHz free running oscillator
   input  AttribRead,                                                     //Configuration Memory Read from Pico
   input  AttribWrite,                                                    //Configuration Memory Write to Pico
   input  MemRead,									  //Common Memory Read from Pico
   input  MemWrite,                                                       //Common Memory Write to Pico
   input  [31:0]MemAddress,                                               //Memory address bus
   input  [15:0]DataIn,                                                   //Data in to peripheral modules
   output [15:0]DataOut,                                                  //Data out FLASH perihperal modules
   input ByteMode,                                                        //8 bit access detection

   output Wait,                                                           //Extend Transfer Request
   output FLASH_CE,                                                       //FLASH Chip Enable
   output FLASH_OE,                                                       //FLASH Output Enable
   output FLASH_WE,                                                       //FLASH Write Enable
   output FLASH_WP,                                                       //FLASH Write Protect
   output FLASH_BYTE,                                                     //FLASH 8 Bit Mode Select
   input  [25:0]FLASH_AIN,                                                //FLASH -> FPGA
   output [25:0]FLASH_AOUT,                                               //FPGA -> FLASH
   output FLASH_AOUT_NEG_ONE,                                             //FPGA -> FLASH LSB
   input  [15:0]FLASH_DIN,                                                //FLASH -> FPGA
   output [15:0]FLASH_DOUT,                                               //FPGA -> FLASH
   output FLASH_TRIS_D,                                                   //FLASH Tristate D0-D14
   output FLASH_TRIS_D15,                                                 //FLASH Tristate D15
   output FLASH_TRIS_A,                                                   //FLASH Tristate A0-A25

   output CPLD_RELOAD_CF,                                                 //CPLD reload										 
   output CPLD_PEEKABOO_CF,                                               //CPLD get last address before load
   input  CPLD_RELOAD_PPC,                                                //CPLD reload from PPC
   input  CPLD_PEEKABOO_PPC,                                              //CPLD get last address before load (from PPC)

   // RAPID HDL 
	`ifdef ENABLE_RAM_PADS
      output [12:0] RamAddr,
      output [0:3]  RamDM,
		output        RamWE,
		output        RamClkE,
		output        RamCS,
		output        RamCAS,
		output        RamRAS,
		output        RamClk,
		output [0:1]  RamBA,
		output [0:31] RamDOut,
		input  [0:31] RamDIn,
		output [0:31] RamDT,
  `endif // RAPID HDL

   `ifdef ENABLE_GPIO 
      input  [4:1]GPIO_IN,
      output [4:1]GPIO_OUT,
	output [4:1]GPIO_TRIS,
   `endif

   `ifdef ENABLE_MDIO 
      input  MDIO_IN,
	output MDIO_OUT,
	output MDC,
	output TRIS_MDIO,
	output ETH_25MHZ,
	output ETH_COMA,
	output ETH_RESET,
   `endif

   //OPB
   input  OPB_Clk,
   input  OPB_Clk90,
   input  OPB_Rst,
   input  [31:0]OPB_ABus,
   input  [3:0]OPB_BE,
   input  [31:0]OPB_DBus,
   input  OPB_RNW,
   input  OPB_select,
   input  OPB_seqAddr,
   output [31:0]Sl_DBus_ext,
   output Sl_errAck_ext,
   output Sl_retry_ext,
   output Sl_toutSup_ext,
   output Sl_xferAck_ext
  );

wire [15:0]FlashDataOut;
wire [15:0]CPLDDataOut;


//--------Rapid HDL wires ----//
wire [12:0] test_bus_read;
wire [12:0] test_bus_write;
wire [15:0] rhdl_dout; // the output data bus for RHDL stuff


//---------Rapid HDL wires SDRAM ------------//
`ifdef ENABLE_RAM_PADS
	wire SDRAMClock;
	wire ram_oe;
	wire [23:0] SYS_ADDR;
	wire [31:0] SYS_DATA_O;
	wire [31:0] SYS_DATA_I;
	wire SYS_WRITE;
	wire SYS_START;
	wire SYS_BUSY;
`endif


//----------------Flash ROM-------------------//
//This module handles reads and writes to the external flash ROM. Features include pre-emptive addressing, and page mode support.
//This module is fully compatable with both 8 and 16 bit hosts.
wire FlashWait;
FlashROM FlashROM(
   .CFClock(CFClock),
   .MemRead(MemRead),
   .MemWrite(MemWrite),
   .DataIn(DataIn[15:0]),
   .DataOut(CPLDDataOut[15:0]),
   .MemAddress(MemAddress[31:0]),
   .ByteMode(ByteMode),
   .CPLD_PEEKABOO_CF(CPLD_PEEKABOO_CF),
   .CPLD_PEEKABOO_PPC(CPLD_PEEKABOO_PPC),
   .FLASH_CE(FLASH_CE),
   .FLASH_OE(FLASH_OE),
   .FLASH_WE(FLASH_WE),
   .FLASH_WP(FLASH_WP),
   .FLASH_BYTE(FLASH_BYTE),
   .FLASH_TRIS_D(FLASH_TRIS_D),
   .FLASH_TRIS_D15(FLASH_TRIS_D15),
   .FLASH_DIN(FLASH_DIN[15:0]),
   .FLASH_DOUT(FLASH_DOUT[15:0]), 
   .FLASH_AOUT(FLASH_AOUT[25:0]),
   .FLASH_AOUT_NEG_ONE(FLASH_AOUT_NEG_ONE),
   .Wait(FlashWait));



//-------CPLD (TurboLoader) Controller--------//
//This module controls the TurboLoader which has the power to switch images and reload the FPGA. The TurboLoader
//can also show the last address loaded into the FPGA before a sucessfull load
CPLDController CPLDController(
   .CFClock(CFClock),
   .AttribRead(AttribRead),
   .AttribWrite(AttribWrite),
   .MemRead(MemRead),
   .MemAddress(MemAddress[31:1]),
   .DataIn(DataIn[15:0]),
   .DataOut(FlashDataOut[15:0]),
   .FLASH_AIN(FLASH_AIN[25:0]),
   .FLASH_TRIS_A(FLASH_TRIS_A),
   .CPLD_PEEKABOO_CF(CPLD_PEEKABOO_CF),
   .CPLD_RELOAD_CF(CPLD_RELOAD_CF),
   .CPLD_PEEKABOO_PPC(CPLD_PEEKABOO_PPC));

//------------Configuration Tuple-------------//
//This module impliments a tuple or "configuration rom"
`ifndef DISABLE_TUPLE
     wire [15:0]TupleDecoderDataOut;     
     TupleDecoder TupleDecoder(
        .AttribRead(AttribRead),
        .MemAddress(MemAddress[10:1]),
        .DataOut(TupleDecoderDataOut[15:0]));
`endif



//--------------Card Identifiers--------------//
//This module returns the Product Code, Firmware version and other information which is defined in PicoDefines.v
`ifdef ENABLE_CARD_INFO
     wire [15:0]CardInfoDataOut;
     CardInfo CardInfo(
        .AttribRead(AttribRead),
        .MemAddress(MemAddress[10:1]),
        .DataOut(CardInfoDataOut[15:0]));
`endif

//-----Internal Logic Analyzer with GPIO------//
`ifdef ENABLE_ILA
	  assign GPIO_OUT[4:1] = 4'b0;
	  assign GPIO_TRIS[4:1] = 4'b1111;
	  wire   [15:0]GPIODataOut = 16'b0;
`elsif ENABLE_GPIO

//------------General Purpose IO--------------/

wire [15:0]GPIODataOut;
wire [4:1]GPIO_IN;
wire [4:1]GPIO_OUT;
wire [4:1]GPIO_TRIS;
GPIO GPIO(
   .CFClock(CFClock),
   .MemRead(MemRead),
   .MemWrite(MemWrite),
   .DataIn(DataIn[15:0]),
   .DataOut(GPIODataOut[15:0]),
   .MemAddress(MemAddress[31:1]),
   .GPIO_IN(GPIO_IN[4:1]),
   .GPIO_OUT(GPIO_OUT[4:1]),
   .GPIO_TRIS(GPIO_TRIS[4:1]));
`endif

//------Xilinx System Generator for DSP-------//
`ifdef ENABLE_SYSGEN
     wire [15:0]SysGenDataOut;
     SysGen SysGen(
        .CLOCK(CLOCK1),
        .MemRead(MemRead),
        .MemWrite(MemWrite),
        .MemAddress(MemAddress[31:1]),
        .DataIn(DataIn[15:0]),
        .DataOut(SysGenDataOut[15:0]));
`endif

//------Ethernet MDIO Interface-------//
`ifdef ENABLE_MDIO
      wire [15:0]MDIODataOut;
		wire MDIOWait;
		MDIO MDIO(
               .CLOCK1(CLOCK1),
               .MemRead(MemRead),
               .MemWrite(MemWrite),
               .MemAddress(MemAddress[31:1]),
               .DataIn(DataIn[15:0]),
               .DataOut(MDIODataOut[15:0]),
               .Wait(MDIOWait),
               .MDIO_IN(MDIO_IN),
               .MDIO_OUT(MDIO_OUT),
               .MDC(MDC),
               .TRIS_MDIO(TRIS_MDIO),
               .ETH_25MHZ(ETH_25MHZ),
               .ETH_COMA(ETH_COMA),
               .ETH_RESET(ETH_RESET));
`endif

`ifdef ENABLE_SIMULATED_BUS_MASTERING //{
wire [15:0]BMtestDataOut;
wire NetGround=0;
reg  comboClock, comboHoldOff;
//synthesis attribute init comboHoldOff 0
//synthesis attribute init comboClock   0
BMTestCounter BMTestCounter
    (.ComboRst    (NetGround),
     .ComboDataOut(BMtestDataOut),  //data returned
     .ComboAddr   (MemAddress),     //address from PCMCIA bus   
     .ComboDataIn (DataIn),         //data    from PCMCIA
     .ComboRd     (MemRead),        //IO Read from PCMCIA bus
     .ComboWr     (MemWrite),       //IO Write to  PCMCIA bus
     .ComboClk    (comboClock));    //Fabricated 'pcmcia clock'
 
always @(posedge CLOCK1)
   begin
   if (!MemRead & !MemWrite)            begin comboHoldOff <= 0;      //end of read/write cycle
                                              comboClock   <= 0; end
   else
   if ((MemRead |  MemWrite) & !comboHoldOff)                         //begininning of read/write cycle
                                        begin comboClock   <= 1; 
                                              comboHoldOff <= 1; end 
   else
   if (comboHoldOff)                    begin comboClock   <= 0; end  //one cycle after beginning.  
   end
`endif //} ENABLE_SIMULATED_BUS_MASTERING

// `ifdef ENABLE_USER_PICOBUS creates a picobus, it also addes the E12toPicoBusBridge which converts
// the 16 bit data from E-12 to 32 bit, and finally also enables the 32 bit BMTestCounter - JBC

`ifdef ENABLE_USER_PICOBUS

   wire [31:0] UserModulePicoDataOut32;
   wire PicoClk;
   wire PicoRst;
   wire [31:0]PicoAddr;
   wire [31:0]PicoDataIn;
   wire [31:0]PicoDataOut;
   wire [15:0]UserModulePicoDataOut;
   wire PicoRd;
   wire PicoWr;
   
   
   E12toPicoBusBridge E12toPicoBusBridge(
      .Clk(CLOCKY9),
      .MemAddress(MemAddress),
      .DataIn(DataIn),
      .DataOut(UserModulePicoDataOut),
      .MemRead(MemRead),
      .MemWrite(MemWrite),
      .PicoRst(PicoRst),
      .PicoClk(PicoClk),
      .PicoAddr(PicoAddr),
      .PicoDataIn(PicoDataIn),
      .PicoDataOut(PicoDataOut),
      .PicoRd(PicoRd),
      .PicoWr(PicoWr)
   );   

// Following counter is used by picoUtil/picodll to test the Bus master.
wire [31:0] BMTestCounterDataOut;
BMTestCounter BMTestCounter(.PicoRst(PicoRst), .PicoClk(PicoClk),  .PicoAddr(PicoAddr[31:0]), .PicoDataIn(PicoDataIn[31:0]), 
                            .PicoDataOut(BMTestCounterDataOut[31:0]), .PicoRd(PicoRd), .PicoWr(PicoWr));

//---------------PicoDataOut Bus------------------//

assign PicoDataOut[31:0] = (
                                                    BMTestCounterDataOut[31:0] |
   `ifdef USER_MODULE_NAME						  UserModulePicoDataOut32[31:0]| `endif
                                                    32'h0
);

`endif // ENABLE_USER_PICOBUS


//ifdef USER_MODULE_NAME allows user to include the instantiations of user modules.
`ifdef USER_MODULE_NAME

   `USER_MODULE_NAME UserModule (
	 `ifdef ENABLE_USER_PICOBUS
         `ifdef USER_CLOCK 
         .Clk50(CLOCK2),
         `endif 
         .PicoRst(PicoRst),
         .PicoClk(PicoClk),
         .PicoAddr(PicoAddr),
         .PicoDataIn(PicoDataIn),
         .PicoRd(PicoRd),
         .PicoWr(PicoWr),
         .PicoDataOut(UserModulePicoDataOut32)
      `endif //ENABLE_USER_PICOBUS

      `ifdef ENABLE_USER_OPB
         `ifdef ENABLE_USER_PICOBUS, `endif
         .OPB_Clk(OPB_Clk),
   //      .OPB_Clk90(OPB_Clk90),
         .OPB_Rst(OPB_Rst),
         .OPB_ABus(OPB_ABus),
         .OPB_BE(OPB_BE),
         .OPB_DBus(OPB_DBus),
         .OPB_RNW(OPB_RNW),
         .OPB_select(OPB_select),
         .OPB_seqAddr(OPB_seqAddr),
         .OPB_Sl_DBus(Sl_DBus_ext),			//JBC took out _ext to OPB bus signals
         .OPB_Sl_errAck(Sl_errAck_ext),
         .OPB_Sl_retry(Sl_retry_ext),
         .OPB_Sl_toutSup(Sl_toutSup_ext),
         .OPB_Sl_xferAck(Sl_xferAck_ext)
      `endif //ENABLE_USER_OPB
   );
   
`endif //USER_MODULE_NAME


//---------Extended Peripheral Bus------------//
rhdl_pico_peripheral rhdl_peripheral (    
	.CLK_I(CFClock), 
   .CLOCK1(CLOCK2),	
	.READ_I(MemRead),     
	.WRITE_I(MemWrite),     
	.ADDR_I(MemAddress),     
	.DATA_I(DataIn),     
	.DATA_O(rhdl_dout),  
	.RESET_O(rhdl_reset),
	.TEST_BUS_READ_I(test_bus_read), 
	.TEST_BUS_WRITE_O(test_bus_write) 
`ifdef ENABLE_RAM_PADS, 
	.RAM_CLK_I(SDRAMClock),
	.SYS_BUSY_I(SYS_BUSY), 
	.SYS_DATA_OUT_I(SYS_DATA_O), 
	.SYS_DATA_IN_O(SYS_DATA_I), 
	.SYS_ADDR_O(SYS_ADDR),	
	.SYS_WRITE_O(SYS_WRITE), 
	.SYS_START_O(SYS_START)
`endif
   );

//------ if RHDL is disabled
/*io_test io_test (
    .CLK_I(CFClock), 
    .READ_I(MemRead), 
    .WRITE_I(MemWrite), 
    .ADDR_I(MemAddress), 
    .DATA_I(DataIn), 
    .DATA_O(rhdl_dout)
    );
*/

//------- Rapid HDL SDRAM Controller --------------//
//`ifdef ENABLE_RAM_PADS  
   
	//100 MHz Clock Generator
	SDRAMClockGen SDRAMClockGen(.CLOCKIN(CLOCK1), .ClockOut(SDRAMClock));
	
	mobile_sdram_ctl mobile_sdram_ctl (
	    .SYS_RESET_I(rhdl_reset), 
	    .SYS_DATA_I(SYS_DATA_I), 
	    .SYS_DATA_O(SYS_DATA_O), 
	    .SYS_ADDR_I(SYS_ADDR), 
	    .SYS_WRITE_I(SYS_WRITE), 
	    .SYS_START_I(SYS_START), 
	    .SYS_BUSY_O(SYS_BUSY), 
	    .SDR_CLK_I(SDRAMClock), 
	    .SDR_CKE_O(RamClkE), 
	    .SDR_ADDR_O(RamAddr), 
	    .SDR_BA_O(RamBA), 
	    .SDR_CS_O(RamCS), 
	    .SDR_RAS_O(RamRAS), 
	    .SDR_CAS_O(RamCAS), 
	    .SDR_WE_O(RamWE), 
	    .SDR_DQM_O(RamDM), 
	    .SDR_DQ_O(RamDOut), 
	    .SDR_DQ_I(RamDIn), 
	    .SDR_OE_O(ram_oe),
	    .TEST_BUS_WRITE_I(test_bus_write),
	    .TEST_BUS_READ_O(test_bus_read)
	    );

	    assign RamClk = SDRAMClock;
	    assign RamDT = {ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe,ram_oe};
//`endif




//---------------DataOut Bus------------------//
//All of the DataOut signals for the peripheral modules are combined here.

assign DataOut[15:0] =                   (FlashDataOut[15:0]          |
   `ifndef DISABLE_TUPLE                  TupleDecoderDataOut[15:0]   | `endif
   `ifdef ENABLE_CARD_INFO                CardInfoDataOut[15:0]       | `endif
   `ifdef ENABLE_GPIO                     GPIODataOut[15:0]           | `endif       
   `ifdef ENABLE_SYSGEN                   SysGenDataOut[15:0]         | `endif
   `ifdef ENABLE_MDIO                     MDIODataOut[15:0]           | `endif
   `ifdef ENABLE_SIMULATED_BUS_MASTERING  BMtestDataOut[15:0]         | `endif 
   `ifdef ENABLE_USER_PICOBUS	          UserModulePicoDataOut[15:0] | `endif 
													   rhdl_dout                    |
                                          CPLDDataOut[15:0]);

assign Wait =               (FlashWait
   `ifdef ENABLE_MDIO     | MDIOWait `endif
   );

endmodule
